package view

import (
	"cloudops/src/common"
	"cloudops/src/config"
	"cloudops/src/models"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"go.uber.org/zap"
	"strconv"
)

// 获取elb列表
func getResourceElbUnbindList(c *gin.Context) {
	sc := c.MustGet(common.GIN_CTX_CONFIG_CONFIG).(*config.ServerConfig)
	allObj, err := models.GetResourceElbAll()
	if err != nil {
		sc.Logger.Error("获取elb列表失败",
			zap.Error(err),
		)
		common.ReqBadFailWithMessage(fmt.Sprintf("获取elb列表失败: %v", err.Error()), c)
		return
	}
	finalList := []*models.ResourceElb{}
	for _, obj := range allObj {
		obj := obj
		obj.Key = fmt.Sprintf("%d", obj.ID)
		if len(obj.BindNodes) > 0 {
			continue
		}
		finalList = append(finalList, obj)
	}
	common.OkWithDetailed(finalList, "ok", c)
}

// 绑定elb到节点
func bindElbToStreeNode(c *gin.Context) {
	sc := c.MustGet(common.GIN_CTX_CONFIG_CONFIG).(*config.ServerConfig)
	// 字段校验
	var reqBind models.BindResourceToStreeNodeRequest
	err := c.ShouldBind(&reqBind)
	if err != nil {
		sc.Logger.Error("解析节点绑定elb请求失败", zap.Any("reqBind", reqBind), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}

	// 字段校验是否必填或合法性
	err = validate.Struct(reqBind)
	if err != nil {
		if errors, ok := err.(validator.ValidationErrors); ok {
			common.ReqBadFailWithWithDetailed(
				gin.H{
					"翻译前": err.Error(),
					"翻译后": errors.Translate(trans),
				},
				"请求出错",
				c,
			)
			return
		}
		common.ReqBadFailWithMessage(err.Error(), c)
		return
	}

	// 根据ID去找节点
	dbNode, err := models.GetStreeNodeById(reqBind.NodeId)
	if err != nil {
		sc.Logger.Error("根据ID获取节点失败", zap.Any("reqBind", reqBind), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}

	// 遍历 elb id数组找到elb对象
	for _, ridStr := range reqBind.ResourceIds {
		rid, _ := strconv.Atoi(ridStr)
		dbResource, err := models.GetResourceElbById(rid)
		if err != nil {
			sc.Logger.Error("根据ID获取elb失败", zap.Any("elb", rid), zap.Error(err))
			common.FailWithMessage(err.Error(), c)
			return
		}
		thisNode := []*models.StreeNode{dbNode}
		tmpM := map[uint]*models.StreeNode{}
		for _, node := range dbResource.BindNodes {
			node := node
			tmpM[node.ID] = node
		}
		tmpM[dbNode.ID] = dbNode
		for _, node := range tmpM {
			node := node
			thisNode = append(thisNode, node)
		}

		// 更新绑定的节点
		err = dbResource.UpdateBindNodes(thisNode)
		if err != nil {
			sc.Logger.Error("更新elb绑定节点失败",
				zap.Any("elb", rid),
				zap.Any("dbResource", dbResource),
				zap.Error(err),
			)
			common.FailWithMessage(err.Error(), c)
			return
		}
	}
	common.OkWithMessage("ELB绑定成功", c)
}

// 取消绑定elb到节点
func unBindElbToStreeNode(c *gin.Context) {
	sc := c.MustGet(common.GIN_CTX_CONFIG_CONFIG).(*config.ServerConfig)
	// 字段校验
	var reqBind models.BindResourceToStreeNodeRequest
	err := c.ShouldBind(&reqBind)
	if err != nil {
		sc.Logger.Error("解析节点绑定elb请求失败", zap.Any("reqBind", reqBind), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}
	// 字段校验是否必填或合法性
	err = validate.Struct(reqBind)
	if err != nil {
		if errors, ok := err.(validator.ValidationErrors); ok {
			common.ReqBadFailWithWithDetailed(
				gin.H{
					"翻译前": err.Error(),
					"翻译后": errors.Translate(trans),
				},
				"请求出错",
				c,
			)
			return
		}
		common.ReqBadFailWithMessage(err.Error(), c)
		return
	}
	// 根据ID去找节点
	dbNode, err := models.GetStreeNodeById(reqBind.NodeId)
	if err != nil {
		sc.Logger.Error("根据ID获取节点失败", zap.Any("reqBind", reqBind), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}
	// 遍历 elb id数组找到elb对象
	for _, ridStr := range reqBind.ResourceIds {
		rid, _ := strconv.Atoi(ridStr)
		dbResource, err := models.GetResourceElbById(rid)
		if err != nil {
			sc.Logger.Error("根据ID获取elb失败", zap.Any("elb", rid), zap.Error(err))
			common.FailWithMessage(err.Error(), c)
			return
		}
		thisNode := []*models.StreeNode{}
		tmpM := map[uint]*models.StreeNode{}
		for _, node := range dbResource.BindNodes {
			node := node
			tmpM[node.ID] = node
		}

		// 将当前树节点的ID，从已绑定的节点中删除
		delete(tmpM, dbNode.ID)
		for _, node := range tmpM {
			node := node
			thisNode = append(thisNode, node)
		}
		// 更新绑定的节点
		err = dbResource.UpdateBindNodes(thisNode)
		if err != nil {
			sc.Logger.Error("更新elb绑定节点失败",
				zap.Any("elb", rid),
				zap.Any("dbResource", dbResource),
				zap.Error(err),
			)
			common.FailWithMessage(err.Error(), c)
			return
		}
	}
	common.OkWithMessage("ELB取消绑定成功", c)
}
